namespace NSpring.Logging.Loggers {

using System;
using System.Text;
//using System.Web.Mail;
using System.Net.Mail;
using NSpring.Logging;
using NSpring.Logging.Common.Pattern;
using NSpring.Logging.Common.Pattern.Patterns;
using NSpring.Logging.DataFormatters;
using NSpring.Logging.EventFormatters;

/// <summary>
/// <para>
/// Each EmailTemplate contains formatting information used to construct 
/// System.Web.Mail.MailMessage objects from Event objects.
/// </para>
/// </summary>
public sealed class EmailTemplate 
{
    private const string BLANK_STRING                   = "";    
    private static PatternParser bodyParser             = new PatternParser(true, true, true, true, true);
    
    private string from;
    private Pattern fromPattern;
    private string to;
    private Pattern toPattern;
    private string cc;
    private Pattern ccPattern;
    private string bcc;
    private Pattern bccPattern;
    private string subject;
    private Pattern subjectPattern;
    private string body;
    private PatternEventFormatter bodyPattern;
    
    //private MailFormat bodyFormat                       = MailFormat.Text;
	private bool isBodyHtml								= false;
    private Encoding bodyEncoding                       = Encoding.UTF8;
	private object monitor								= new object();
    
    private DataFormatter dataFormatter;
    
    private EmailTemplate() {}
    
    /// <summary>
    /// Constructs a new instance
    /// </summary>
    /// <param name="_from">The hard-coded string or pattern used to create the "From" field of MailMessage objects</param>
    /// <param name="_to">The hard-coded string or pattern used to create the "To" field of MailMessage objects</param>
    /// <param name="_cc">The hard-coded string or pattern used to create the "Cc" field of MailMessage objects</param>
    /// <param name="_bcc">The hard-coded string or pattern used to create the "Bcc" field of MailMessage objects</param>
    /// <param name="_subject">The hard-coded string or pattern used to create the "Subject" field of MailMessage objects</param>
    /// <param name="_body">The hard-coded string or pattern used to create the "Body" field of MailMessage objects</param>
    public EmailTemplate(string _from, string _to, string _cc, string _bcc, string _subject, string _body) 
	{
        dataFormatter = new TreeDataFormatter();
        From = _from;
        To = _to;
        CC = _cc;
        BCC = _bcc;
        Subject = _subject;
        Body = _body;
    }
    
    /// <summary>
    /// The MailFormat set on each System.Web.Mail.MailMessage object created
    /// </summary>
	//public MailFormat BodyFormat {
	//    get {
	//        return isBodyHtml;
	//    }
	//    set {
	//        isBodyHtml = value;
	//    }
	//}
	public bool IsBodyHtml
	{
		get { return isBodyHtml; }
		set { isBodyHtml = value; }
	}
    
    /// <summary>
    /// The BodyEncoding set on each System.Web.Mail.MailMessage object created
    /// </summary>
    public Encoding BodyEncoding {
        get {
            return bodyEncoding;
        }
        set {
            if (value == null) {
                throw new ArgumentNullException();
            }
            bodyEncoding = value;
        }
    }
    
    /// <summary>
    /// The hard-coded string or pattern used to create the "From" field of MailMessage objects
    /// </summary>
    public string From {
        get {
            return from;
        }
        set {
            if (value == null) {
                throw new ArgumentNullException();
            }
            lock (monitor) {
                from = value;
                fromPattern = new SummaryPattern(from);
            }
        }
    }
    
    /// <summary>
    /// The hard-coded string or pattern used to create the "To" field of MailMessage objects
    /// </summary>
    public string To {
        get {
            return to;
        }
        set {
            if (value == null) {
                throw new ArgumentNullException();
            }
            lock (monitor) {
                to = value;
                toPattern = new SummaryPattern(to);
            }
        }
    }
    
    /// <summary>
    /// The hard-coded string or pattern used to create the "Cc" field of MailMessage objects
    /// </summary>
    public string CC {
        get {
            return cc;
        }
        set {
            lock (monitor) {
                if (value == null) {
                    cc = null;
                    ccPattern = null;
                }
                else {
                    ccPattern = new SummaryPattern(value);
                    cc = value;
                }
            }
        }
    }
    
    /// <summary>
    /// The hard-coded string or pattern used to create the "Bcc" field of MailMessage objects
    /// </summary>
    public string BCC {
        get {
            return bcc;
        }
        set {
            lock (monitor) {
                if (value == null) {
                    bcc = null;
                    bccPattern = null;
                }
                else {
                    bccPattern = new SummaryPattern(value);
                    bcc = value;
                }
            }
        }
    }
    
    /// <summary>
    /// The hard-coded string or pattern used to create the "Subject" field of MailMessage objects
    /// </summary>
    public string Subject {
        get {
            return subject;
        }
        set {
            lock (monitor) {
                if (value == null) {
                    subject = null;
                    subjectPattern = null;
                }
                else {
                    subjectPattern = new SummaryPattern(value);
                    subject = value;
                }
            }
        }
    }
    
    /// <summary>
    /// The hard-coded string or pattern used to create the "Body" field of MailMessage objects
    /// </summary>
    public string Body {
        get {
            return body;
        }
        set {
            if (value == null) {
                throw new ArgumentNullException();
            }
            lock (monitor) {
                bodyPattern = new PatternEventFormatter(body);
                bodyPattern.DataFormatter = dataFormatter;
                body = value;
            }
        }
    }
    
    /// <summary>
    /// The DataFormatter used to format data objects
    /// </summary>
    public DataFormatter DataFormatter {
        set {
            if (value == null) {
                throw new ArgumentNullException();
            }
            lock (monitor) {
                bodyPattern.DataFormatter = value;
                dataFormatter = value;
            }
        }
    }
    
    public MailMessage CreateMessage(NSpring.Logging.Event _event, EventFormatter _formatter) 
	{
        if (_event == null) {
            throw new ArgumentNullException();
        }
        Pattern pattern;
        MailMessage message = new MailMessage();
        
        message.From = new MailAddress(fromPattern.Format(_event));
        
        pattern = toPattern;
        message.To.Add(pattern.Format(_event));
        
        pattern = ccPattern;
        if (pattern != null)
			message.CC.Add(pattern.Format(_event));
        
        pattern = bccPattern;
        if (pattern != null)
			message.Bcc.Add(pattern.Format(_event));
        
        pattern = subjectPattern;
        if (pattern != null) {
            message.Subject = pattern.Format(_event);
        }
        
        message.Body = bodyPattern.Format(_event);

        Level level = _event.Level;
        if (level >= Level.Warning) {
            message.Priority = MailPriority.High;
        }
        else if (level > Level.Verbose) {
            message.Priority = MailPriority.Normal;
        }
        else {
            message.Priority = MailPriority.Low;
        }

		//message.BodyFormat = bodyFormat;
		message.IsBodyHtml = isBodyHtml;
        message.BodyEncoding = bodyEncoding;
        
        return message;
    }
}

}
